﻿#include "FITKAbaqusHDF5AdaptorInteractionProperty.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"

#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Writer.h"

#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractInteractionProperty.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionPropertyContact.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionContactTangentialBehavior.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionContactNormalBehavior.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInteractionContactBehavior.h"

namespace IO
{
    QString FITKAbaqusHDF5AdaptorInteractionProperty::getAdaptorClass()
    {
        return "FITKAbaqusHDF5AbaqusAdaptorInteraction";
    }

    bool FITKAbaqusHDF5AdaptorInteractionProperty::adaptR()
    {
        auto sectionAssign = dynamic_cast<Interface::FITKAbaAbstractInteractionProperty*>(_dataObj);
        if (!_reader || !_h5Group || !sectionAssign) return false;
        bool isR = true;
        isR &= readInteractionProperty(sectionAssign, *_h5Group);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorInteractionProperty::adaptW()
    {
        auto sectionAssign = dynamic_cast<Interface::FITKAbaAbstractInteractionProperty*>(_dataObj);
        if (!_writer || !_h5Group || !sectionAssign) return false;
        bool isW = true;
        isW &= writeInteractionProperty(sectionAssign, *_h5Group);
        return isW;
    }
    bool FITKAbaqusHDF5AdaptorInteractionProperty::readInteractionProperty(Interface::FITKAbaAbstractInteractionProperty * property, H5::Group & h5Group)
    {
        if (!property) return false;
        bool isR = true;
        isR &= readNDataObject(property, h5Group);
        isR &= readInteractionPropertyContact(property, h5Group);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorInteractionProperty::readInteractionPropertyContact(Interface::FITKAbaAbstractInteractionProperty* property, H5::Group& h5Group)
    {
        auto interactionProperty = dynamic_cast<Interface::FITKAbaInteractionPropertyContact*>(property);
        if (!interactionProperty) return false;
        bool isR = true;
        bool isValid = false;

        //read count
        if (!h5Group.attrExists("BehaviorCount")) return false;
        int behaviorsCount = readIntAttribute(h5Group, "BehaviorCount");
        for (int i = 0; i < behaviorsCount; ++i)
        {
            if (!h5Group.nameExists(std::to_string(i))) return false;
            auto group = h5Group.openGroup(std::to_string(i));

            if (!group.attrExists("BehaviorType")) return false;
            auto behaviorType = readStrAttribute(group, "BehaviorType");
            Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType> fitkBTypeTrafer;
            bool isValid = false;
            auto eBehaviorType = fitkBTypeTrafer.fromString(QString::fromStdString(behaviorType), isValid);
            if (!isValid) return false;

            interactionProperty->addBehavior(eBehaviorType);
            auto behavoir = interactionProperty->getBehavoir(eBehaviorType);
            if (!behavoir) return false;

            if (eBehaviorType == Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType::NormalHehavior)
            {
                auto behavior = dynamic_cast<Interface::FITKAbaInteractionContactNormalBehavior*>(behavoir);
                if (!behavior) return false;

                auto pressureOverclosure = readStrAttribute(group, "PressureOverclosure");
                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactEnum::PressureOverclosure> fitkPTypeTrafer;
                auto ePressureOverclosure = fitkPTypeTrafer.fromString(QString::fromStdString(pressureOverclosure), isValid);
                if (!isValid) return false;
                behavior->setPressureOverclosure(ePressureOverclosure);

                auto constraintEnforcementMethod = readStrAttribute(group, "ConstraintEnforcementMethod");
                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactEnum::ConstraintEnformentMethod> fitkCETypeTrafer;
                auto eConstraintEnforcementMethod = fitkCETypeTrafer.fromString(QString::fromStdString(constraintEnforcementMethod), isValid);
                if (!isValid) return false;
                behavior->setConstraintEnforcementMethod(eConstraintEnforcementMethod);

                bool AllowSeparationAfterContact = readBoolAttribute(group, "AllowSeparationAfterContact");
                behavior->setAllowSeparationAfterContact(AllowSeparationAfterContact);

            }
            else if (eBehaviorType == Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType::TangentialBehavior)
            {
                auto behavior = dynamic_cast<Interface::FITKAbaInteractionContactTangentialBehavior*>(behavoir);
                if (!behavior) return false;

                auto frictionFormulation = readStrAttribute(group, "FrictionFormulation");
                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactBehaviorEnum::FrictionFormulation> fitkFFTypeTrafer;
                auto eFrictionFormulation = fitkFFTypeTrafer.fromString(QString::fromStdString(frictionFormulation), isValid);
                if (!isValid) return false;
                behavior->setFrictionFormulation(eFrictionFormulation);

                auto frictionDirectionality = readStrAttribute(group, "FrictionDirectionality");
                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FrictionDiretionalityEnum::FrictionDiretionality> fitkFDTypeTrafer;
                auto eFrictionDirectionality = fitkFDTypeTrafer.fromString(QString::fromStdString(frictionDirectionality), isValid);
                if (!isValid) return false;
                behavior->setFrictionDirectionality(eFrictionDirectionality);

                bool UseSlipRateDependentData = readBoolAttribute(group, "UseSlipRateDependentData");
                behavior->setUseSlipRateDependentData(UseSlipRateDependentData);
                bool UseContactPressureDependentData = readBoolAttribute(group, "UseContactPressureDependentData");
                behavior->setUseContactPressureDependentData(UseContactPressureDependentData);
                bool UseTemperatureDependentData = readBoolAttribute(group, "UseTemperatureDependentData");
                behavior->setUseTemperatureDependentData(UseTemperatureDependentData);

                int RowCount = readIntAttribute(group, "RowCount");
                for (int i = 0; i < RowCount; ++i)
                {
                    double FrictionCoeff = readDoubleAttribute(group, "FrictionCoeff");
                    behavior->setFrictionCoeff(FrictionCoeff, i);
                    double FrictionCoeff1 = readDoubleAttribute(group, "FrictionCoeff1");
                    behavior->setFrictioinCoeff1(FrictionCoeff1, i);
                    double FrictionCoeff2 = readDoubleAttribute(group, "FrictionCoeff2");
                    behavior->setFrictionCoeff2(FrictionCoeff2, i);
                    double SlipRate = readDoubleAttribute(group, "SlipRate");
                    behavior->setSlipRate(SlipRate, i);
                    double ContactPressure = readDoubleAttribute(group, "ContactPressure");
                    behavior->setContactPressure(ContactPressure, i);
                    double Temperature = readDoubleAttribute(group, "Temperature");
                    behavior->setTemperature(Temperature, i);
                }
            }
            else if (eBehaviorType == Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType::ThermalConductance)
            {
                return false;
            }

        }

        return isR;
    }

    bool FITKAbaqusHDF5AdaptorInteractionProperty::writeInteractionProperty(Interface::FITKAbaAbstractInteractionProperty * property, H5::Group & h5Group)
    {
        if (!property) return false;
        bool isW = true;
        bool isValid = false;

        std::string groupName = createParentAttribute(property, h5Group);
        if (groupName.empty())return false;

        _h5CreateGroup = h5Group.createGroup(groupName);
        isW &= writeInteractionPropertyContact(property, _h5CreateGroup);
        isW &= writeNDataObject(property, _h5CreateGroup);

        //写出类型
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractInteractionProperty::FITKAbaInteractionPropertyType> fitkIPTypeTrafer;
        QString sType = fitkIPTypeTrafer.toStrting(property->getInteractionPropertyType(), isValid);
        if (!isValid) return false;
        writeStrAttribute(_h5CreateGroup, "Type", sType.toStdString());
        return isW;
    }
    bool FITKAbaqusHDF5AdaptorInteractionProperty::writeInteractionPropertyContact(Interface::FITKAbaAbstractInteractionProperty * property, H5::Group & h5Group)
    {
        auto interactionProperty = dynamic_cast<Interface::FITKAbaInteractionPropertyContact*>(property);
        if (!interactionProperty) return false;
        bool isW = true;
        bool isValid = false;

        auto behaviors = interactionProperty->getBehaviors();
        //write count
        int behaviorsCount = behaviors.size();
        writeIntAttribute(h5Group, "BehaviorCount", &behaviorsCount);

        for (int i = 0; i < behaviors.size(); ++i)
        {
            auto group = h5Group.createGroup(std::to_string(i));

            auto behaviorType = behaviors[i]->getBehaviorType();
            if (behaviorType == Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType::NormalHehavior)
            {
                auto behavior = dynamic_cast<Interface::FITKAbaInteractionContactNormalBehavior*>(behaviors[i]);
                if (!behavior) return false;

                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactEnum::PressureOverclosure> fitkPOTypeTrafer;
                auto pressureOverclosure = fitkPOTypeTrafer.toStrting(behavior->getPressureOverclosure(), isValid);
                if (!isValid) return false;
                writeStrAttribute(group, "PressureOverclosure", pressureOverclosure.toStdString());

                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactEnum::ConstraintEnformentMethod> fitkCEypeTrafer;
                auto constraintEnforcementMethod = fitkCEypeTrafer.toStrting(behavior->getConstraintEnforcementMethod(), isValid);
                if (!isValid) return false;
                writeStrAttribute(group, "ConstraintEnforcementMethod", constraintEnforcementMethod.toStdString());

                bool AllowSeparationAfterContact = behavior->getAllowSeparationAfterContact();
                writeBoolAttribute(group, "AllowSeparationAfterContact", &AllowSeparationAfterContact);

            }
            else if (behaviorType == Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType::TangentialBehavior)
            {
                auto behavior = dynamic_cast<Interface::FITKAbaInteractionContactTangentialBehavior*>(behaviors[i]);
                if (!behavior) return false;

                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactBehaviorEnum::FrictionFormulation> fitkFFTypeTrafer;
                auto frictionFormulation = fitkFFTypeTrafer.toStrting(behavior->getFrictionFormulation(), isValid);
                if (!isValid) return false;
                writeStrAttribute(group, "FrictionFormulation", frictionFormulation.toStdString());

                //枚举转换字符
                Core::FITKEnumTransfer<Interface::FrictionDiretionalityEnum::FrictionDiretionality> fitkFDTypeTrafer;
                auto frictionDirectionality = fitkFDTypeTrafer.toStrting(behavior->getFrictionDirectionality(), isValid);
                if (!isValid) return false;
                writeStrAttribute(group, "FrictionDirectionality", frictionDirectionality.toStdString());

                bool UseSlipRateDependentData = behavior->getUseSlipRateDependentData();
                writeBoolAttribute(group, "UseSlipRateDependentData", &UseSlipRateDependentData);
                bool UseContactPressureDependentData = behavior->getUseContactPressureDependentData();
                writeBoolAttribute(group, "UseContactPressureDependentData", &UseContactPressureDependentData);
                bool UseTemperatureDependentData = behavior->getUseTemperatureDependentData();
                writeBoolAttribute(group, "UseTemperatureDependentData", &UseTemperatureDependentData);

                int RowCount = behavior->getRowCount();
                writeIntAttribute(group, "RowCount", &RowCount);

                for (int i = 0; i < RowCount; ++i)
                {
                    double FrictionCoeff = behavior->getFrictionCoeff(i);
                    writeDoubleAttribute(group, "FrictionCoeff", &FrictionCoeff);
                    double FrictionCoeff1 = behavior->getFrictionCoeff1(i);
                    writeDoubleAttribute(group, "FrictionCoeff1", &FrictionCoeff1);
                    double FrictionCoeff2 = behavior->getFrictionCoeff2(i);
                    writeDoubleAttribute(group, "FrictionCoeff2", &FrictionCoeff2);
                    double SlipRate = behavior->getSlipRate(i);
                    writeDoubleAttribute(group, "SlipRate", &SlipRate);
                    double ContactPressure = behavior->getContactPressure(i);
                    writeDoubleAttribute(group, "ContactPressure", &ContactPressure);
                    double Temperature = behavior->getTemperature(i);
                    writeDoubleAttribute(group, "Temperature", &Temperature);
                }
            }
            else if (behaviorType == Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType::ThermalConductance)
            {
                return false;
            }

            Core::FITKEnumTransfer<Interface::FITKAbaInteractionContactBehaviorEnum::FITKAbaContactBehaviorType> fitkCBTypeTrafer;
            QString sBehaviorType = fitkCBTypeTrafer.toStrting(behaviorType, isValid);
            if (!isValid) return false;

            writeStrAttribute(group, "BehaviorType", sBehaviorType.toStdString());
        }


        return isW;
    }
}